<template>
  <div class="Crud-dialog">
    <a-modal v-model:visible="props.visible" v-bind="modalConfig">
      <template #footer>
        <a-button key="back" @click="handleCancel">{{ modalConfig.cancelText }}</a-button>
        <a-button key="back" @click="handleOk">{{ modalConfig.okText }}</a-button>
      </template>
      <a-form :model="formValue" v-bind="formConfig">
        <a-row>
          <template v-for="(item, index) in props.formItems" :key="index">
            <a-col v-bind="item.colLayout || { span: 12 }">
              <a-form-item :label="item.label" v-bind="formItemConfig">
                <!-- 动态组件 -->
                <!-- ['a-switch','a-checkbox','a-radio'] -->
                <template v-if="['a-switch', 'a-checkbox', 'a-radio'].includes(item.type)">
                  <component :is="item.type" :name="item.key" v-model:checked="formValue[item.key]" v-on:[`${item.eventName}`]="createFunctionFromString(item, item.eventName, formValue)" v-if="item.show || true"> </component>
                </template>
                <template v-else>
                  <component :is="item.type" :name="item.key" v-model:value="formValue[item.key]" v-on:[`${item.eventName}`]="createFunctionFromString(item, item.eventName, formValue)" :disabled="item.disabled || false" v-if="item.show || true">
                    <component :is="subComponents(item.type)" v-for="(option, i) in item.options" :key="i" :value="option.value">{{ option.label }}</component>
                  </component>
                </template>
              </a-form-item>
            </a-col>
          </template>
        </a-row>
      </a-form>
    </a-modal>
  </div>
</template>

<script lang="ts" setup name="CrudDialog">
import { FormItemsType, ComponentType, componentMap, FormType, FormItemType, FormItemConfigType, FormConfigType, ModalConfigType } from './type'
const props = defineProps({
  visible: {
    type: Boolean,
    required: true
  },
  formItems: {
    type: Array as () => FormItemsType[],
    required: true
  },
  formData: {
    type: Object,
    required: true
  }
})
const emits = defineEmits(['submit', 'cancel'])

// 拿到父组件 传给子组件 没有通过prop接受的属性
const { modalConfig, formItemConfig, formConfig } = useAttrs() as { modalConfig: ModalConfigType; formItemConfig: FormConfigType; formConfig: FormItemConfigType }

// 根据formItems的key 初始化对象
const form: FormType = props.formItems.reduce((acc, curr) => {
  acc[curr.key] = ['a-checkbox-group'].includes(curr.type) ? [] : ''
  return acc
}, {} as FormType)

let formValue = reactive({ ...form, ...props.formData })

// 动态绑定函数 传参
type MyFunctionType = (args: any) => any
const createFunctionFromString = (item: FormItemType, functionName?: string, formValue?: FormType) => {
  if (functionName) {
    const func = new Function(`return ${item[functionName]}`) as unknown as MyFunctionType

    const funCall = func(formValue)

    if (typeof funCall === 'function') {
      formValue && funCall(formValue[item.key], formValue)
    }
  }
}

// 父组件修改值 后传给子组件
watch(
  () => props.formData,
  (newV) => {
    Object.assign(formValue, newV)
  },
  { deep: true, immediate: true }
)

// 映射生成子组件
const subComponents = computed(() => {
  return (type: ComponentType) => {
    const typeValue = componentMap.get(type)
    return typeValue
  }
})
const handleOk = () => {
  emits('submit', formValue)
}

const handleCancel = () => {
  emits('cancel', formValue)
}
</script>

<style lang="less">
@import './index.less';
</style>
